/*
 * $Id: MailGenerator.java,v 1.8 2009/11/09 21:01:16 navdeep_mahajan Exp $
 *
 * Copyright (C) 2006 General Electric Company. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 *
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */

package com.ge.healthcare.autosc.common.util.mail.support;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.common.database.dao.IFileTransferDetailsDAO;
import com.ge.healthcare.autosc.common.database.dao.IRequestDefn2SweepPropertiesDAO;
import com.ge.healthcare.autosc.common.database.dao.IRequestListUserDAO;
import com.ge.healthcare.autosc.common.database.dao.ISweepPropertiesDAO;
import com.ge.healthcare.autosc.common.database.dao.ITaskDAO;
import com.ge.healthcare.autosc.common.database.pojo.AbstractTask;
import com.ge.healthcare.autosc.common.database.pojo.ActFileTransferDetails;
import com.ge.healthcare.autosc.common.database.pojo.ActRequest;
import com.ge.healthcare.autosc.common.database.pojo.ActRequestListUser;
import com.ge.healthcare.autosc.common.database.pojo.ActTask;
import com.ge.healthcare.autosc.common.dbLogger.StepLogger;
import com.ge.healthcare.autosc.common.exceptions.PropertyException;
import com.ge.healthcare.autosc.common.util.ApplicationInfo;
import com.ge.healthcare.autosc.common.util.PropertyConstants;
import com.ge.healthcare.autosc.common.util.mail.Attachment;
import com.ge.healthcare.autosc.common.util.mail.MailConstants;
import com.ge.healthcare.autosc.common.util.mail.MailInfo;

public class MailGenerator {
	private static ITaskDAO taskDAO = null;
	private static IRequestDefn2SweepPropertiesDAO rqDefn2SweepPropDAO = null;
	private static IRequestListUserDAO rqListUserDAO = null;

	private static IFileTransferDetailsDAO fileDAO = null;
	private static MailTextGenerator mailTextGenerator = null;

	public static final String MSG_TXT_REPORT_ONLY = "---   results are available on the ASC network   ---\n";
	public static final String MSG_TXT_NO_FILES_FOUND = "---   no files were associated with this request   ---\n";
	/**
	 * Number of bytes in a kilobyte.
	 */
	public static final int BYTES_PER_KBYTE = 1024;

	public static final String MSG_TXT_MAX_EMAIL_SIZE = "--- Request Files Exceed Max E-mail File Size Thus Not Attached ---\n";
	public static final String MSG_TXT_FILES_ATTACHED = "--- Request Files Attached to Message ---\n";

	public MailInfo generate(ActRequest request, ActTask task)
			throws PropertyException {
		MailInfo mailInfo = null;
		mailInfo = initMailInfo();
		String emailBody = generateEmailBody(request, task);

		String subject = mailTextGenerator.generateSubject(request);
		mailInfo.setEmailSubject(subject);

		if (!isNotifyOnly(request)) {
			emailBody = attachFiles(mailInfo, emailBody, request);
		} else {
			emailBody = replaceReturnFileContent(emailBody, MSG_TXT_REPORT_ONLY);
		}
		mailInfo.setEmailBody(emailBody);

		String[] recipients = buildToRecipients(task);
		mailInfo.setRecipients(recipients);

		String[] ccRecipients = buildCcRecipients(request);
		if (!ASCUtil.isNullOrEmptyArray(ccRecipients)) {
			mailInfo.setCcRecipients(ccRecipients);
		}
		return mailInfo;
	}

	protected String attachFiles(MailInfo mailInfo, String emailBody,
			ActRequest request) throws PropertyException {
		String maxMsgSizeStr = ApplicationInfo.getInstance()
				.getRequiredPropertyValue(PropertyConstants.MAIL_MAX_KBYTES);
		int maxMsgSize = Integer.parseInt(maxMsgSizeStr);
		// I am aware that I am doing this query in the txt generator as well
		// but doing the separate query keeps some separation of responsibility.
		// Probably going to regret this later
		List<ActFileTransferDetails> files = fileDAO
				.getExternalFileTransferLstByRequestId(request.getRequestId());
		Set<Attachment> attachments = new HashSet<Attachment>();
		if (!ASCUtil.isNullOrEmptyList(files)) {
			int sizeBytes = 0;
			//We are checking direction as put files are also considered external files
			for (ActFileTransferDetails file : files) {
				if (!file.isFailed() && 
						IFileTransferDetailsDAO.UPLOAD_FROM_DEVICE.equalsIgnoreCase(file.getDirection())) {
					sizeBytes += file.getContentSize();

					Attachment attachment = new Attachment();
					attachment.setAttachmentName(file.getFileName());
					String filePath = file.getFile().getAbsolutePath();
					attachment.setAttachmentFileName(filePath);
					attachments.add(attachment);
				}
			}
			int sizeInKb = sizeBytes / BYTES_PER_KBYTE;
			if (maxMsgSize > sizeInKb) {
				mailInfo.addAttachments(attachments);
				emailBody = replaceReturnFileContent(emailBody,
						MSG_TXT_FILES_ATTACHED);

				StringBuffer log = new StringBuffer(MSG_TXT_FILES_ATTACHED);
				log.append("Attached files total size(KB): ").append(sizeInKb);
				StepLogger.addStepLog(log.toString());

			} else {
				StringBuffer msg = new StringBuffer(MSG_TXT_MAX_EMAIL_SIZE);
				msg.append(MSG_TXT_REPORT_ONLY);
				emailBody = replaceReturnFileContent(emailBody, msg.toString());

				StringBuffer log = new StringBuffer(MSG_TXT_MAX_EMAIL_SIZE);
				log.append("Unable to attach files total size(KB): ").append(
						sizeInKb);
				StepLogger.addStepLog(log.toString());
			}
		} else {
			emailBody = replaceReturnFileContent(emailBody,
					MSG_TXT_NO_FILES_FOUND);
			StringBuffer log = new StringBuffer(MSG_TXT_NO_FILES_FOUND);
			log.append("For Request: ").append(request.getRequestId());
			StepLogger.addStepLog(log.toString());
		}
		return emailBody;
	}

	private String replaceReturnFileContent(String txt, String replacement) {
		return txt.replaceAll(MailConstants.MSG_RETURN_FILE_CONTENT,
				replacement);
	}

	/**
	 * If the Request Defn Property Report Only is exists then no attachments
	 * should be attached
	 * 
	 * @param request
	 * @return
	 */
	protected boolean isNotifyOnly(ActRequest request) {
		boolean isNotifyOnly = false;
		Map<String, String> props = null;
		props = rqDefn2SweepPropDAO.getSweepPropForRequestDefn(request
				.getRequestDefnId());
		// If Report Only exists Then no Attachments
		if (props != null && props.containsKey(ISweepPropertiesDAO.REPORT_ONLY)) {
			isNotifyOnly = true;
		}
		return isNotifyOnly;
	}

	/**
	 * Get the all the tasks that lead up to task in order more or less. To
	 * create notify correctly the parent task that called this task needs to be
	 * in 0 index.
	 * 
	 * @param task
	 * @return
	 */
	protected List<AbstractTask> getTasks(ActTask task) {
		List<ActTask> reverseTasks = new ArrayList<ActTask>();
		// Notify should never be called as the inital "task" thus there should
		// be 1 to n parent tasks
		// reverseTasks.add(task);
		Long parentId = task.getParentId();
		while (!ASCUtil.isNullOrEmptyObject(parentId)) {
			ActTask parentTask = taskDAO.getTaskByID(parentId);
			// should not be null but paranoia
			if (!ASCUtil.isNullOrEmptyObject(parentTask)) {
				reverseTasks.add(parentTask);
				parentId = parentTask.getParentId();
			}
		}
		// The task list is currently in reverse order from what it needs to be
		List<AbstractTask> tasks = new ArrayList<AbstractTask>();
		for (ActTask iTask : reverseTasks) {
			tasks.add(iTask);
		}
		return tasks;
	}

	/**
	 * Get the tasks for the calling tasks in the correct order and call
	 * MailTextGenerator
	 * 
	 * @param request
	 * @param task
	 * @return
	 */
	private String generateEmailBody(ActRequest request, ActTask task) {
		List<AbstractTask> tasks = getTasks(task);
		return mailTextGenerator.generate(request, tasks);
	}

	/**
	 * If the Request Defn has an Email Property that e-mail should be copied on
	 * all notifications
	 * 
	 * @param request
	 * @return
	 */
	protected String[] buildCcRecipients(ActRequest request) {
		List<String> ccRecipients = null;
		Map<String, String> props = null;
		props = rqDefn2SweepPropDAO.getSweepPropForRequestDefn(request
				.getRequestDefnId());
		if (!ASCUtil.isNullOrEmptyMap(props)
				&& props.containsKey(ISweepPropertiesDAO.EMAIL)) {
			StringBuffer msg = new StringBuffer("CC Value set to: ");
			String cc = props.get(ISweepPropertiesDAO.EMAIL);
			if (!ASCUtil.isNullOrEmpty(cc)) {
				ccRecipients = new ArrayList<String>();
				msg.append(cc);
				ccRecipients.add(cc);
			} else {
				return null;
			}
			ASCLogger
					.info(this.getClass(), "buildCcRecipients", msg.toString());
			StepLogger.addStepLog(msg.toString());
			return ccRecipients.toArray(new String[1]);
		} else {
			return null;
		}
	}

	/**
	 * Create the list of To: recipients for the e-mail notification. Detailed
	 * logic is found in the DAO
	 * 
	 * @param task
	 * @return
	 */
	protected String[] buildToRecipients(ActTask task) {
		List<ActRequestListUser> users = rqListUserDAO
				.getNotifyRecipients(task);
		StringBuffer log = new StringBuffer("Sending Notify to: ");
		String[] recipients = new String[0];
		if (!ASCUtil.isNullOrEmptyList(users)) {
			List<String> toAddresses = new ArrayList<String>();
			for (ActRequestListUser user : users) {
				log.append(user.getEmailAddress()).append(", ");
				toAddresses.add(user.getEmailAddress());
			}
			recipients = toAddresses.toArray(new String[users.size()]);
		} else {
			log.append(" No Recipients Found ");
		}
		StepLogger.addStepLog(log.toString());
		return recipients;
	}

	/**
	 * Initialize the MailInfo Object
	 * 
	 * @return
	 * @throws PropertyException
	 */
	protected MailInfo initMailInfo() throws PropertyException {
		MailInfo mailInfo = new MailInfo();
		String serverHostName = ApplicationInfo.getInstance()
				.getRequiredPropertyValue(
						PropertyConstants.MAIL_DEFAULT_SMTP_HOST);
		mailInfo.setServerHostName(serverHostName);

		String senderAddress = ApplicationInfo
				.getInstance()
				.getRequiredPropertyValue(PropertyConstants.MAIL_DEFAULT_SENDER);
		mailInfo.setSenderAddress(senderAddress);
		return mailInfo;
	}

	/**
	 * @param taskDAO
	 *            the taskDAO to set
	 */
	public void setTaskDAO(ITaskDAO taskDAO) {
		MailGenerator.taskDAO = taskDAO;
	}

	/**
	 * @param rqDefn2SweepPropDAO
	 *            the rqDefn2SweepPropDAO to set
	 */
	public void setRqDefn2SweepPropDAO(
			IRequestDefn2SweepPropertiesDAO rqDefn2SweepPropDAO) {
		MailGenerator.rqDefn2SweepPropDAO = rqDefn2SweepPropDAO;
	}

	/**
	 * @param requestListUserDAO
	 *            the iRequestListUserDAO to set
	 */
	public void setRqListUserDAO(IRequestListUserDAO requestListUserDAO) {
		MailGenerator.rqListUserDAO = requestListUserDAO;
	}

	/**
	 * @param fileDAO
	 *            the fileDAO to set
	 */
	public void setFileDAO(IFileTransferDetailsDAO fileDAO) {
		MailGenerator.fileDAO = fileDAO;
	}

	/**
	 * @param mailTextGenerator
	 *            the mailTextGenerator to set
	 */
	public void setMailTextGenerator(MailTextGenerator mailTextGenerator) {
		MailGenerator.mailTextGenerator = mailTextGenerator;
	}
}
